﻿using Newtonsoft.Json;
using Quartz.Util;
using System;
using System.Buffers;
using System.IO;
using System.Net.WebSockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using XiAnAirport.DAL;
using XiAnAirport.Models;

namespace XiAnAirport.BUS.RocketMQ
{
    public class FXMQClient
    {
        public string aes_key = string.Empty;
        public string server_addr = string.Empty;
        public string websocket_addr = string.Empty;
        public string IdentityTopic = string.Empty;
        public string IdentityTag = string.Empty;
        public string ThirdPartyTopic = string.Empty;
        public static string PanoramicTopic = string.Empty;
        public string IdentityGroup = string.Empty;
        public string ThirdPartyGroup = string.Empty;
        public static string PanoramicGroup = string.Empty;
        public string AccessKey = string.Empty;
        public string SecretKey = string.Empty;
        public static string version = string.Empty;
        public static ClientWebSocket webSocketClient;
        static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
        static CancellationToken _cancellationToken = _cancellationTokenSource.Token;
        public bool IsReg = false;
        public bool IsSubscribe = false;
        public FXMQClient()
        {
            try
            {
                aes_key = AppSettingsHelper.Configuration["MQ:PrivateKey"];
                server_addr = AppSettingsHelper.Configuration["MQ:Server"];
                websocket_addr = AppSettingsHelper.Configuration["MQ:WebSocketUrl"];
                IdentityTopic = AppSettingsHelper.Configuration["MQ:IdentityTopic"];
                IdentityTag = AppSettingsHelper.Configuration["MQ:IdentityTag"];
                ThirdPartyTopic = AppSettingsHelper.Configuration["MQ:ThirdPartyTopic"];
                PanoramicTopic = AppSettingsHelper.Configuration["MQ:PanoramicTopic"];
                IdentityGroup = AppSettingsHelper.Configuration["MQ:IdentityGroup"];
                ThirdPartyGroup = AppSettingsHelper.Configuration["MQ:ThirdPartyGroup"];
                PanoramicGroup = AppSettingsHelper.Configuration["MQ:PanoramicGroup"];
                AccessKey = AppSettingsHelper.Configuration["MQ:AccessKey"];
                SecretKey = AppSettingsHelper.Configuration["MQ:SecretKey"];
                version = AppSettingsHelper.Configuration["MQ:Version"];
                Task t = Task.Factory.StartNew(async () =>
                {
                    while (true)
                    {
                        try
                        {
                            if (webSocketClient == null || webSocketClient.State != WebSocketState.Open)
                            {
                                //连接服务端
                                bool result = ConnectServer(websocket_addr).Result;
                            }
                        }
                        catch (Exception ex)
                        {

                        }
                        Task.Delay(60000).Wait();
                    }
                });
            }
            catch (Exception ex)
            {
                LogHelper.Log("连接MQ组件异常" + ex.ToString());
            }

        }

        public async Task<bool> ConnectServer(string url)
        {
            bool result = false;
            webSocketClient = await CreateAsync(url);
            if (webSocketClient != null)
            {
                result = true;
                _ = Task.Run(async () =>
                {
                    var buffer = ArrayPool<byte>.Shared.Rent(1024);
                    try
                    {
                        while (webSocketClient.State == WebSocketState.Open)
                        {
                            //var result = await webSocketClient.ReceiveAsync(buffer, CancellationToken.None);
                            var result = await webSocketClient.ReceiveAsync(buffer, _cancellationToken);
                            if (result.MessageType == WebSocketMessageType.Close)
                            {
                                throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, result.CloseStatusDescription);
                            }
                            var text = Encoding.UTF8.GetString(buffer.AsSpan(0, result.Count));
                            LogHelper.Log(text);
                            string value = @"{""type"":""consumer"",""context"":""";
                            int index = text.IndexOf(value);
                            if (index > -1)
                            {
                                string data = text.Substring(index + 30, text.Length - 32);
                                ConsumeMessageInfo consumeMessageInfo = JsonConvert.DeserializeObject<ConsumeMessageInfo>(data);
                                if (consumeMessageInfo != null)
                                {
                                    if (consumeMessageInfo.topic == IdentityTopic)
                                    {
                                        IdentityDataProcess(consumeMessageInfo.msg);
                                    }
                                }
                            }
                        }
                    }
                    finally
                    {
                        ArrayPool<byte>.Shared.Return(buffer);
                    }
                });
            }
            return result;
        }

        public static async Task<bool> Produce(string data)
        {
            ProduceInfo produceInfo = new ProduceInfo();
            produceInfo.command = "publish";
            produceInfo.topic = PanoramicTopic;
            produceInfo.group = PanoramicGroup;
            produceInfo.tag = "*";
            produceInfo.msg = data;
            return SendMessage(JsonConvert.SerializeObject(produceInfo)).Result;
        }

        public static async Task<bool> SendMessage(string message)
        {
            try
            {
                var sendStr = Encoding.UTF8.GetBytes(message);
                await webSocketClient.SendAsync(sendStr, WebSocketMessageType.Text, true, _cancellationToken);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public string ToHexs(byte[] data)
        {
            if (data.Length <= 0) return "";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sb.Append(data[i].ToString("X2"));
            }
            string str = sb.ToString();
            return str;
        }

        public string AESDecrypt(string str, string key)
        {
            try
            {
                if (string.IsNullOrEmpty(str)) return null;
                Byte[] toEncryptArray = Convert.FromBase64String(str);

                RijndaelManaged rm = new RijndaelManaged
                {
                    Key = Encoding.UTF8.GetBytes(key),
                    Mode = CipherMode.ECB,
                    Padding = PaddingMode.PKCS7,
                    BlockSize = 128
                };

                ICryptoTransform cTransform = rm.CreateDecryptor();
                Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

                return Encoding.UTF8.GetString(resultArray);
            }
            catch (Exception ex)
            {
                LogHelper.Log("密码解密异常" + ex.ToString());
                return "";
            }
        }

        public void ThirdPartyDataProcess(ThirdPartyData thirdPartyData)
        {
            if (thirdPartyData.dataType == version + "/DeviceStatusTotal/01" || thirdPartyData.dataType == version + "/DeviceStatusTotal/02" || thirdPartyData.dataType == version + "/DeviceStatusTotal/03")
            {
                LogHelper.Log(thirdPartyData.data.ToString());
                DeviceStatusTotal deviceStatusTotal = JsonConvert.DeserializeObject<DeviceStatusTotal>(thirdPartyData.data.ToString());
                if (deviceStatusTotal != null)
                {
                    MqttDataBUS mqttDataBUS = new MqttDataBUS();
                    mqttDataBUS.MqttDataProcess(deviceStatusTotal, "DeviceStatusTotal", thirdPartyData.dataType.Substring(thirdPartyData.dataType.Length - 2, 2));
                }
            }
            else if (thirdPartyData.dataType == version + "/TodayProcess/01" || thirdPartyData.dataType == version + "/TodayProcess/02" || thirdPartyData.dataType == version + "/TodayProcess/03")
            {
                MqttDataBUS mqttDataBUS = new MqttDataBUS();
                TodayProcess todayProcess = JsonConvert.DeserializeObject<TodayProcess>(thirdPartyData.data.ToString());
                if (todayProcess != null)
                {
                    mqttDataBUS.MqttDataProcess(todayProcess, "TodayProcess", thirdPartyData.dataType.Substring(thirdPartyData.dataType.Length - 2, 2));
                }
            }
            else if (thirdPartyData.dataType == version + "/TodayRuntime/01" || thirdPartyData.dataType == version + "/TodayRuntime/02" || thirdPartyData.dataType == version + "/TodayRuntime/03")
            {
                MqttDataBUS mqttDataBUS = new MqttDataBUS();
                TodayRuntime todayRuntime = JsonConvert.DeserializeObject<TodayRuntime>(thirdPartyData.data.ToString());
                if (todayRuntime != null)
                {
                    string id = thirdPartyData.dataType.Substring(thirdPartyData.dataType.Length - 2, 2);
                    string manufacturer = string.Empty;
                    if (id == "01")
                    {
                        manufacturer = "Schindler";
                    }
                    else if (id == "02")
                    {
                        manufacturer = "TKE";
                    }
                    else
                    {
                        manufacturer = "TOSHIBA";
                    }
                    todayRuntime.runtime = Math.Round(todayRuntime.runtime, 2);
                    mqttDataBUS.MqttDataProcess(id, manufacturer, "TodayRuntime", todayRuntime.runtime);
                }
            }
            else if (thirdPartyData.dataType == version + "/FaultStatistics/01" || thirdPartyData.dataType == version + "/FaultStatistics/02" || thirdPartyData.dataType == version + "/FaultStatistics/03")
            {
                MqttDataBUS mqttDataBUS = new MqttDataBUS();
                FaultStatistics faultStatistics = JsonConvert.DeserializeObject<FaultStatistics>(thirdPartyData.data.ToString());
                if (faultStatistics != null)
                {
                    mqttDataBUS.MqttFaultStatistics(thirdPartyData.dataType.Substring(thirdPartyData.dataType.Length - 2, 2), "FaultStatistics", faultStatistics.faultTotal, faultStatistics.faultToday);
                }
            }
            else if (thirdPartyData.dataType == version + "/FaultRecordReport/01" || thirdPartyData.dataType == version + "/FaultRecordReport/02" || thirdPartyData.dataType == version + "/FaultRecordReport/03")
            {
                MqttDataBUS mqttDataBUS = new MqttDataBUS();
                FaultRecordReport faultRecordReport = JsonConvert.DeserializeObject<FaultRecordReport>(thirdPartyData.data.ToString());
                if (faultRecordReport != null)
                {
                    string id = thirdPartyData.dataType.Substring(thirdPartyData.dataType.Length - 2, 2);
                    string manufacturer = string.Empty;
                    if (id == "01")
                    {
                        faultRecordReport.manufacturer = "Schindler";
                    }
                    else if (id == "02")
                    {
                        faultRecordReport.manufacturer = "TKE";
                    }
                    else
                    {
                        faultRecordReport.manufacturer = "TOSHIBA";
                    }

                    mqttDataBUS.MqttFaultRecordDataProcess(faultRecordReport);
                }
            }

        }

        public void IdentityDataProcess(string data)
        {
            DataSyncInfo datainfo = JsonConvert.DeserializeObject<DataSyncInfo>(data);
            if (datainfo != null)
            {
                AuthInfo authInfo = JsonConvert.DeserializeObject<AuthInfo>(datainfo.data.ToString());
                if (authInfo != null)
                {
                    if (authInfo.type == "org")
                    {
                        AuthOrganizationInfo organizationInfo = JsonConvert.DeserializeObject<AuthOrganizationInfo>(datainfo.data.ToString());
                        if (organizationInfo != null)
                        {
                            OrganizationDAL organizationDAL = new OrganizationDAL();
                            if (organizationInfo.operateType == "add")
                            {
                                int id = organizationDAL.QuerySyncOrganizationId(organizationInfo.id);
                                if (id > 0)
                                {
                                    organizationDAL.EditOrganizationById(organizationInfo, id);
                                }
                                else
                                {
                                    organizationDAL.AddOrganization(organizationInfo);
                                }
                            }
                            else if (organizationInfo.operateType == "update")
                            {
                                organizationDAL.EditOrganization(organizationInfo);
                            }
                            else if (organizationInfo.operateType == "delete")
                            {
                                organizationDAL.DelOrganization(organizationInfo);
                            }
                        }
                    }
                    else if (authInfo.type == "user")
                    {
                        AuthAccountInfo authAccountInfo = JsonConvert.DeserializeObject<AuthAccountInfo>(datainfo.data.ToString());
                        if (authAccountInfo != null)
                        {
                            authAccountInfo.password = AESDecrypt(authAccountInfo.password, aes_key);
                            UserRoleDAL userRoleDAL = new UserRoleDAL();
                            if (authAccountInfo.operateType == "add")
                            {
                                int id = userRoleDAL.QueryAccount(authAccountInfo.id);
                                if (id > 0)
                                {
                                    userRoleDAL.EditSyncAccount(authAccountInfo, id);
                                }
                                else
                                {
                                    userRoleDAL.AddAccount(authAccountInfo);
                                }
                            }
                            else if (authAccountInfo.operateType == "update")
                            {
                                userRoleDAL.EditAccount(authAccountInfo);
                            }
                            else if (authAccountInfo.operateType == "delete")
                            {
                                userRoleDAL.DelAccount(authAccountInfo);
                            }
                        }
                    }
                }
            }
        }

        public ClientWebSocket webSocket;
        public async Task ConnnectSocket()
        {
            webSocket = await CreateAsync("ws://192.168.0.114:5000/ws");
            if (webSocket != null)
            {
                _ = Task.Run(async () =>
                {
                    var buffer = ArrayPool<byte>.Shared.Rent(1024);
                    try
                    {
                        while (webSocket.State == WebSocketState.Open)
                        {
                            var result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
                            if (result.MessageType == WebSocketMessageType.Close)
                            {
                                throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, result.CloseStatusDescription);
                            }
                            var text = Encoding.UTF8.GetString(buffer.AsSpan(0, result.Count));

                        }
                    }
                    finally
                    {
                        ArrayPool<byte>.Shared.Return(buffer);
                    }
                });
            }
            else
            {
                Console.WriteLine("服务连接失败!");
            }

        }

        /// <summary>
        /// 创建客户端实例
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<ClientWebSocket> CreateAsync(string ServerUri)
        {
            if (webSocketClient != null)
            {
                _cancellationTokenSource.Cancel();
                _cancellationTokenSource = new CancellationTokenSource();
                _cancellationToken = _cancellationTokenSource.Token;
                //await webSocketClient.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
            }
            var webSocket = new ClientWebSocket();
            webSocket.Options.RemoteCertificateValidationCallback = delegate { return true; };

            await webSocket.ConnectAsync(new Uri(ServerUri), CancellationToken.None);
            if (webSocket.State == WebSocketState.Open)
            {
                return webSocket;
            }
            return null;
        }

    }
}

